/**
 * @file gpio_config.c
 * @author automation (you@domain.com)
 * @brief 用于DI、DO的数字开关量的GPIO的配置及初始化
 * @version 0.1
 * @date 2022-03-09
 * 
 * @copyright Copyright (c) 2022
 * 
 */

#include <stdint.h>
#include "bsp.h"
#include "stm32f4xx_hal.h"
#include "gpio_config.h"


/**
 * @brief GPIO针脚配置
 * 
 */
typedef enum {
    EN_24V_PR = 0,
    EN_5V,
    // EN_V_SERVO_MOTOR,    // 取消
    EN_3V_JOINT_ENC,
    EN_3V_PR_ENC,
    LED_STA_OK,
    LED_STA_ERR,    // 5
    JOG_BACK,       
    JOG_FORWARD,
    JOG_SHRINK,
    JOG_EXTEND,
    ID1,            // 10
    ID2,            
    ID3,
    HOME_INDEX1,
    JOINT_ENC_CS,
    PR_CS,          // 15
    BEEP,
    FRAM_CS,
    OUTER_FLASH_CS,
    GPIO_NUMBER
}gpioList_e;

typedef struct __attribute__ ((__packed__))
{
    uint32_t gpio_pin;
    uint32_t gpio_speed;
    uint32_t gpio_mode;
    uint32_t gpio_pull;

    GPIO_TypeDef* gpio_port;
    void (*rccCfg)(void);
//    void (*defaultStatCfg)(void);
//    void (*defaultStatCfg)(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
    uint8_t init_state;
}gpioTable_t;


void RCC_GPIOA_ENABLE(void)
{
    __HAL_RCC_GPIOA_CLK_ENABLE();
}

void RCC_GPIOB_ENABLE(void)
{
    __HAL_RCC_GPIOB_CLK_ENABLE();
}

void RCC_GPIOC_ENABLE(void)
{
    __HAL_RCC_GPIOC_CLK_ENABLE();
}

#define NO_NEED 3

gpioTable_t gpioTable[GPIO_NUMBER] =
    {
        [EN_24V_PR] =
            {
                .gpio_pin = EN_24V_PR_Pin,
                .gpio_port = EN_24V_PR_GPIO_Port,
                .gpio_mode = GPIO_MODE_OUTPUT_PP,
                .gpio_pull = GPIO_PULLUP,
                .gpio_speed = GPIO_SPEED_FREQ_LOW,
                .rccCfg = RCC_GPIOC_ENABLE,
                .init_state = GPIO_PIN_SET,
            },
        [EN_5V] =
            {
                .gpio_pin = EN_5V_SHOE_Pin,
                .gpio_port = EN_5V_SHOE_GPIO_Port,
                .gpio_mode = GPIO_MODE_OUTPUT_PP,
                .gpio_pull = GPIO_PULLUP,
                .gpio_speed = GPIO_SPEED_FREQ_LOW,
                .rccCfg = RCC_GPIOC_ENABLE,
                .init_state = GPIO_PIN_SET,
            },
        [EN_3V_JOINT_ENC] =
            {
                .gpio_pin = EN_3V_JOINT_ENC_Pin,
                .gpio_port = EN_3V_JOINT_ENC_GPIO_Port,
                .gpio_mode = GPIO_MODE_OUTPUT_PP,
                .gpio_pull = GPIO_PULLUP,
                .gpio_speed = GPIO_SPEED_FREQ_LOW,
                .rccCfg = RCC_GPIOB_ENABLE,
                .init_state = GPIO_PIN_SET,
            },
        [EN_3V_PR_ENC] =
            {
                .gpio_pin = EN_3V_PR_ENC_Pin,
                .gpio_port = EN_3V_PR_ENC_GPIO_Port,
                .gpio_mode = GPIO_MODE_OUTPUT_PP,
                .gpio_pull = GPIO_PULLUP,
                .gpio_speed = GPIO_SPEED_FREQ_LOW,
                .rccCfg = RCC_GPIOB_ENABLE,
                .init_state = GPIO_PIN_SET,
            },
        [LED_STA_OK] =
            {
                .gpio_pin = LED_STA_OK_Pin,
                .gpio_port = LED_STA_OK_GPIO_Port,
                .gpio_mode = GPIO_MODE_OUTPUT_PP,
                .gpio_pull = GPIO_NOPULL,
                .gpio_speed = GPIO_SPEED_FREQ_LOW,
                .rccCfg = RCC_GPIOB_ENABLE,
                .init_state = GPIO_PIN_RESET,
            },
        [LED_STA_ERR] =
            {
                .gpio_pin = LED_STA_ERR_Pin,
                .gpio_port = LED_STA_ERR_GPIO_Port,
                .gpio_mode = GPIO_MODE_OUTPUT_PP,
                .gpio_pull = GPIO_NOPULL,
                .gpio_speed = GPIO_SPEED_FREQ_LOW,
                .rccCfg = RCC_GPIOB_ENABLE,
                .init_state = GPIO_PIN_RESET,
            },
        [JOG_BACK] =
            {
                .gpio_pin = JOG_BACK_Pin,
                .gpio_port = JOG_BACK_GPIO_Port,
                .gpio_mode = GPIO_MODE_INPUT,
                .gpio_pull = GPIO_NOPULL,
                .gpio_speed = GPIO_SPEED_FREQ_LOW,
                .rccCfg = RCC_GPIOA_ENABLE,
                .init_state = NO_NEED,
            },
        [JOG_FORWARD] =
            {
                .gpio_pin = JOG_FORWARD_Pin,
                .gpio_port = JOG_FORWARD_GPIO_Port,
                .gpio_mode = GPIO_MODE_INPUT,
                .gpio_pull = GPIO_NOPULL,
                .gpio_speed = GPIO_SPEED_FREQ_LOW,
                .rccCfg = RCC_GPIOA_ENABLE,
                .init_state = NO_NEED,
            },
        [JOG_SHRINK] =
            {
                .gpio_pin = JOG_SHRINK_Pin,
                .gpio_port = JOG_SHRINK_GPIO_Port,
                .gpio_mode = GPIO_MODE_INPUT,
                .gpio_pull = GPIO_NOPULL,
                .gpio_speed = GPIO_SPEED_FREQ_LOW,
                .rccCfg = RCC_GPIOA_ENABLE,
                .init_state = NO_NEED,
            },
        [JOG_EXTEND] =
            {
                .gpio_pin = JOG_EXTEND_Pin,
                .gpio_port = JOG_EXTEND_GPIO_Port,
                .gpio_mode = GPIO_MODE_INPUT,
                .gpio_pull = GPIO_NOPULL,
                .gpio_speed = GPIO_SPEED_FREQ_LOW,
                .rccCfg = RCC_GPIOA_ENABLE,
                .init_state = NO_NEED,
            },
        [ID1] =
            {
                .gpio_pin = ID1_Pin,
                .gpio_port = ID1_GPIO_Port,
                .gpio_mode = GPIO_MODE_INPUT,
                .gpio_pull = GPIO_PULLUP,
                .gpio_speed = GPIO_SPEED_FREQ_LOW,
                .rccCfg = RCC_GPIOC_ENABLE,
                .init_state = NO_NEED,
            },
        [ID2] =
            {
                .gpio_pin = ID2_Pin,
                .gpio_port = ID2_GPIO_Port,
                .gpio_mode = GPIO_MODE_INPUT,
                .gpio_pull = GPIO_PULLUP,
                .gpio_speed = GPIO_SPEED_FREQ_LOW,
                .rccCfg = RCC_GPIOC_ENABLE,
                .init_state = NO_NEED,
            },
        [ID3] =
            {
                .gpio_pin = ID3_Pin,
                .gpio_port = ID3_GPIO_Port,
                .gpio_mode = GPIO_MODE_INPUT,
                .gpio_pull = GPIO_PULLUP,
                .gpio_speed = GPIO_SPEED_FREQ_LOW,
                .rccCfg = RCC_GPIOC_ENABLE,
                .init_state = NO_NEED,
            },
        [HOME_INDEX1] =
            {
                .gpio_pin = HOME_INDEX_Pin,
                .gpio_port = HOME_INDEX_GPIO_Port,
                .gpio_mode = GPIO_MODE_INPUT,
                .gpio_pull = GPIO_NOPULL,
                .gpio_speed = GPIO_SPEED_FREQ_LOW,
                .rccCfg = RCC_GPIOB_ENABLE,
                .init_state = NO_NEED,
            },
        [JOINT_ENC_CS] =
            {
                .gpio_pin = JOINT_ENC_CS_Pin,
                .gpio_port = JOINT_ENC_CS_GPIO_Port,
                .gpio_mode = GPIO_MODE_OUTPUT_PP,
                .gpio_pull = GPIO_PULLUP,
                .gpio_speed = GPIO_SPEED_FREQ_HIGH,
                .rccCfg = RCC_GPIOA_ENABLE,
                .init_state = GPIO_PIN_SET,
            },
        [PR_CS] =
            {
                .gpio_pin = PR_CS_Pin,
                .gpio_port = PR_CS_GPIO_Port,
                .gpio_mode = GPIO_MODE_OUTPUT_PP,
                .gpio_pull = GPIO_PULLUP,
                .gpio_speed = GPIO_SPEED_FREQ_HIGH,
                .rccCfg = RCC_GPIOB_ENABLE,
                .init_state = GPIO_PIN_SET,
            },
        [BEEP] =
            {
                .gpio_pin = BEEP_Pin,
                .gpio_port = BEEP_GPIO_Port,
                .gpio_mode = GPIO_MODE_OUTPUT_PP,
                .gpio_pull = GPIO_PULLDOWN,
                .gpio_speed = GPIO_SPEED_FREQ_LOW,
                .rccCfg = RCC_GPIOB_ENABLE,
                .init_state = GPIO_PIN_RESET,
            },
        [FRAM_CS] =
            {
                .gpio_pin = FRAM_CS_Pin,
                .gpio_port = FRAM_CS_GPIO_Port,
                .gpio_mode = GPIO_MODE_OUTPUT_PP,
                .gpio_pull = GPIO_PULLUP,
                .gpio_speed = GPIO_SPEED_FREQ_HIGH,
                .rccCfg = RCC_GPIOA_ENABLE,
                .init_state = GPIO_PIN_SET,
            },
        [OUTER_FLASH_CS] =
            {
                .gpio_pin = OUTER_FLASH_CS_Pin,
                .gpio_port = OUTER_FRAM_CS_GPIO_Port,
                .gpio_mode = GPIO_MODE_OUTPUT_PP,
                .gpio_pull = GPIO_PULLUP,
                .gpio_speed = GPIO_SPEED_FREQ_HIGH,
                .rccCfg = RCC_GPIOC_ENABLE,
                .init_state = GPIO_PIN_SET,
            },
};

#define GPIO_NOW (gpioTable[order_num]) 
/**
 * @brief 对单个gpio分别初始化
 * 
 * @param order_num gpio编号
 */
void gpioInitSeparate(uint16_t order_num)
{
    GPIO_InitTypeDef gpio_init_struct = {0};
    gpioTable[order_num].rccCfg();

    // 设置gpio针脚初始状态
    if (GPIO_NOW.init_state != NO_NEED)
    {
        HAL_GPIO_WritePin(GPIO_NOW.gpio_port, GPIO_NOW.gpio_pin, (GPIO_PinState)GPIO_NOW.init_state);
    }

    gpio_init_struct.Pin = gpioTable[order_num].gpio_pin;
    gpio_init_struct.Mode = gpioTable[order_num].gpio_mode;
    gpio_init_struct.Pull = gpioTable[order_num].gpio_pull;
    gpio_init_struct.Speed = gpioTable[order_num].gpio_speed;
    HAL_GPIO_Init(gpioTable[order_num].gpio_port, &gpio_init_struct);
}

/**
 * @brief 初始化通用gpio
 * 
 */
void gpioInit(void)
{
    for(uint16_t i = 0; i < GPIO_NUMBER; i++)
    {
        gpioInitSeparate(i);
    }
}
